#include "QsUdp.h"
#include "QsUdpReceiver.h"
#include <QMutex>
#include <QMutexLocker>
#include <QThread>
#include <QMetaType>
#include <QSettings>
#include <QJsonObject>

QsUdp* QsUdp::m_instance = nullptr;

QsUdp* QsUdp::instance()
{
    static QMutex mutex;
    if (!m_instance) {
        QMutexLocker locker(&mutex);
        if (!m_instance) {
            m_instance = new QsUdp();
        }
    }
    return m_instance;
}

QsUdp::QsUdp(QObject* parent)
    : QsUdp(QsUdpInfo(QHOSTADDRESS_ANY_COMPAT, 45454), parent)
{
    // 委托构造，无需重复初始化
}

QsUdp::QsUdp(const QsUdpInfo& info, QObject* parent)
    : QObject(parent)
    , m_info(info)
{
    qRegisterMetaType<QsUdpPacketHeader>("QsUdpPacketHeader");
    qRegisterMetaType<QsUdpInfo>("QsUdpInfo");
    m_sender = new QUdpSocket(this);
    m_receiver = new QsUdpReceiver(m_info);
    m_receiverThread = new QThread(this);
    m_receiver->moveToThread(m_receiverThread);
    connect(m_receiver, &QsUdpReceiver::received, this, &QsUdp::received);
    m_receiverThread->start();
}

QsUdp::~QsUdp()
{
    if (m_receiver) {
        // 先调用接收器的清理方法
        QMetaObject::invokeMethod(m_receiver, "cleanup", Qt::QueuedConnection);
    }
    
    if (m_receiverThread) {
        // 停止线程
        m_receiverThread->quit();
        // 等待线程结束，最多等待3秒
        if (!m_receiverThread->wait(3000)) {
            // 如果线程没有在3秒内退出，强制终止
            m_receiverThread->terminate();
            m_receiverThread->wait();
        }
    }
    
    // 删除接收器对象
    if (m_receiver) {
        m_receiver->deleteLater();
    }
}

void QsUdp::init(const QsUdpInfo& info)
{
    // 更新UDP信息
    m_info = info;
    
    QMetaObject::invokeMethod(m_receiver, "init", Qt::QueuedConnection,
                              Q_ARG(QsUdpInfo, m_info));
}

void QsUdp::setInfo(const QsUdpInfo& info)
{
    if (info.port != m_info.port || info.address != m_info.address) {
        m_info = info;
        // 重新初始化接收器
        QMetaObject::invokeMethod(m_receiver, "init", Qt::QueuedConnection,
                                  Q_ARG(QsUdpInfo, m_info));
    }
}

void QsUdp::send(quint16 msgType, const QByteArray& data, quint16 r1, quint16 r2)
{
    QsUdpPacketHeader header;
    header.length = data.size();
    header.msgType = msgType;
    header.reserved1 = r1;
    header.reserved2 = r2;
    QByteArray packet;
    packet.append(reinterpret_cast<const char*>(&header), sizeof(header));
    packet.append(data);
    // 发送到配置的地址和端口
    m_sender->writeDatagram(packet, m_info.address, m_info.port);
}

QsUdp* QsUdp::setSocketOption(QAbstractSocket::SocketOption option, const QVariant& value)
{
    if (m_sender) {
        m_sender->setSocketOption(option, value);
    }
    return this;
}

QsUdp* QsUdp::setReceiverSocketOption(QAbstractSocket::SocketOption option, const QVariant& value)
{
    if (m_receiver) {
        QMetaObject::invokeMethod(m_receiver, "setSocketOption", Qt::QueuedConnection,
                                  Q_ARG(QAbstractSocket::SocketOption, option), Q_ARG(QVariant, value));
    }
    return this;
}

QsUdp* QsUdp::enableBroadcast(bool enabled)
{
    if (m_sender) {
        m_sender->setSocketOption(QAbstractSocket::BroadcastTtlOption, enabled ? 1 : 0);
    }
    if (m_receiver) {
        QMetaObject::invokeMethod(m_receiver, "enableBroadcast", Qt::QueuedConnection,
                                  Q_ARG(bool, enabled));
    }
    return this;
}

bool QsUdp::joinMulticastGroup(const QHostAddress& groupAddress, const QNetworkInterface& iface)
{
    if (m_receiver) {
        bool result = false;
        QMetaObject::invokeMethod(m_receiver, "joinMulticastGroup", Qt::BlockingQueuedConnection,
                                  Q_RETURN_ARG(bool, result),
                                  Q_ARG(QHostAddress, groupAddress), Q_ARG(QNetworkInterface, iface));
        return result;
    }
    return false;
}

bool QsUdp::leaveMulticastGroup(const QHostAddress& groupAddress, const QNetworkInterface& iface)
{
    if (m_receiver) {
        bool result = false;
        QMetaObject::invokeMethod(m_receiver, "leaveMulticastGroup", Qt::BlockingQueuedConnection,
                                  Q_RETURN_ARG(bool, result),
                                  Q_ARG(QHostAddress, groupAddress), Q_ARG(QNetworkInterface, iface));
        return result;
    }
    return false;
}

void QsUdp::setConfigFromIni(const QString& iniFile, const QString& group)
{
    QSettings settings(iniFile, QSettings::IniFormat);
    settings.beginGroup(group);
    QVariantMap map;
    for (const QString& key : settings.childKeys()) {
        map[key] = settings.value(key);
    }
    settings.endGroup();
    setConfig(map);
}

void QsUdp::setConfig(const QVariantMap& map)
{
    if (map.contains("port")) {
        setPort(map.value("port").toUInt());
    }
    if (map.contains("address")) {
        setAddress(QHostAddress(map.value("address").toString()));
    }
    if (map.contains("sendBufferSize")) {
        setSocketOption(QAbstractSocket::SendBufferSizeSocketOption, map.value("sendBufferSize"));
    }
    if (map.contains("recvBufferSize")) {
        setReceiverSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, map.value("recvBufferSize"));
    }
    if (map.contains("broadcast")) {
        enableBroadcast(map.value("broadcast").toBool());
    }
    if (map.contains("multicastGroup")) {
        joinMulticastGroup(QHostAddress(map.value("multicastGroup").toString()));
    }
}

void QsUdp::setConfig(const QJsonObject& obj)
{
    setConfig(obj.toVariantMap());
} 